package wang.lxl.concurrent.lockTest;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 生产者,消费者错误写法(运行示例图:等待唤醒机制图1)
 */
public class ProducerAndConsumerTestForLock {
    public static void main(String[] args) {
        // 用lock实现等待唤醒机制
        Clerk clerk = new ClerkForLock();
        Producer pro = new Producer(clerk);
        Consumer consumer = new Consumer(clerk);
        new Thread(pro, "生产者A").start();
        new Thread(consumer, "消费者B").start();
        new Thread(pro, "生产者C").start();
        new Thread(consumer, "消费者D").start();
    }
}

/**
 * 店员类4
 */
class ClerkForLock implements Clerk {
    private int product = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    // 进货
    public void get() {// 去掉 synchronized 关键字
        lock.lock();// 加锁
        try {
            while (product >= 1) {
                System.out.println("产品已满");
                try {
//                    this.wait();
                    condition.await();// 等待
                } catch (InterruptedException e) {}
            }
            System.out.println(Thread.currentThread().getName() + " : " + ++product);
//            this.notifyAll();
            condition.signalAll();// 唤醒
        }finally {
            lock.unlock();// 解锁,记得一定要放到finally中
        }
    }
    // 卖货
    public void sell() {// 去掉 synchronized 关键字
        lock.lock();// 加锁
        try {
            while (product <= 0) {
                System.out.println("缺货");
                try {
//                    this.wait();// 为了避免虚假唤醒问题,应该总是使用在循环中
                    condition.await();// 等待
                } catch (InterruptedException e) {}
            }
            System.out.println(Thread.currentThread().getName() + " : " + --product);
//            this.notifyAll();
            condition.signalAll();// 唤醒
        }finally {
            lock.unlock();// 解锁,一定要放到finally中
        }
    }
}
